//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package cn.zyjblogs.starter.web.hander;

import cn.zyjblogs.starter.common.entity.response.HttpCode;
import cn.zyjblogs.starter.common.entity.response.ResponseObject;
import cn.zyjblogs.starter.common.entity.response.ResponseResult;
import cn.zyjblogs.starter.common.exception.AbstractBusinessException;
import cn.zyjblogs.starter.common.exception.AbstractFrameworkException;
import java.util.List;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import cn.zyjblogs.starter.common.exception.AuthRuntimeException;
import ma.glasnost.orika.MappingException;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

/**
 * @author zhuyijun
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);


    @ExceptionHandler({NoHandlerFoundException.class})
    @ResponseStatus(org.springframework.http.HttpStatus.NOT_FOUND)
    public ResponseObject<?> handleNoHandlerFoundException(NoHandlerFoundException exception) {
        log.error("NoHandlerFound", exception);
        String i18nCode = "web_starter_not_found";
        return ResponseResult.error(HttpCode.NOT_FOUND, i18nCode);
    }

    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public ResponseObject<?> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException exception) {
        log.error("HttpRequestMethodNotSupported", exception);
        String i18nCode = "web_starter_method_not_allowed";
        return ResponseResult.error(HttpCode.METHOD_NOT_ALLOWED, i18nCode);
    }

    @ExceptionHandler({HttpMediaTypeNotSupportedException.class})
    public ResponseObject<?> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException exception) {
        log.error("HttpMediaTypeNotSupported", exception);
        String i18nCode = "web_starter_unsupported_media_type";
        return ResponseResult.error(HttpCode.UNSUPPORTED_MEDIA_TYPE, i18nCode);
    }

    @ExceptionHandler({MethodArgumentTypeMismatchException.class})
    public ResponseObject<String> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException exception) {
        String i18nCode = "web_starter_property_format_error";
        return ResponseResult.error(HttpCode.BAD_REQUEST, i18nCode);
    }

    @ExceptionHandler({ConstraintViolationException.class})
    public ResponseObject<String> handleConstraintViolationException(ConstraintViolationException exception) {
        Set<ConstraintViolation<?>> constraintViolations = exception.getConstraintViolations();
        String i18nCode;
        if (CollectionUtils.isEmpty(constraintViolations)) {
            log.warn("全局异常捕获到了ConstraintViolationException，但是没有发现错误", exception);
            i18nCode = "web_starter_bad_request";
            return ResponseResult.error(HttpCode.BAD_REQUEST, i18nCode);
        } else {
            i18nCode = constraintViolations.stream().findFirst().get().getMessage();
            return ResponseResult.error(HttpCode.BAD_REQUEST, i18nCode);
        }
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    public ResponseObject<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException exception) {
        BindingResult bindingResult = exception.getBindingResult();
        return this.getByBindingResult(bindingResult);
    }

    @ExceptionHandler({AbstractFrameworkException.class})
    public ResponseObject<?> handleFrameworkException(AbstractFrameworkException exception) {
        log.error("全局异常捕获 系统异常：{}", exception.getMessage());
        return ResponseResult.error(HttpCode.INTERNAL_SERVER_ERROR, exception.getMessage());
    }
    @ExceptionHandler({AuthRuntimeException.class})
    public ResponseObject<?> handleBusinessException(AuthRuntimeException exception) {
        log.error("全局异常捕获 系统异常：", exception);
        return ResponseResult.error(HttpCode.INTERNAL_SERVER_ERROR, exception.getMessage());
    }

    @ExceptionHandler({AbstractBusinessException.class})
    public ResponseObject<?> handleBusinessException(AbstractBusinessException exception) {
        log.error("全局异常捕获 系统异常：", exception);
        return ResponseResult.error(HttpCode.INTERNAL_SERVER_ERROR, exception.getMessage());
    }
    @ExceptionHandler({BadSqlGrammarException.class})
    public ResponseObject<?> handleSqlException(Exception exception) {
        log.error("全局异常捕获 SQL执行异常：{}", exception.getMessage());
        return ResponseResult.error(HttpCode.INTERNAL_SERVER_ERROR, "SQL执行异常",exception.getMessage());
    }

    @ExceptionHandler({BindException.class})
    public ResponseObject<?> handleBindException(BindException exception) {
        BindingResult bindingResult = exception.getBindingResult();
        return this.getByBindingResult(bindingResult);
    }

    @ExceptionHandler({HttpMessageNotReadableException.class})
    public ResponseObject<?> handleHttpMessageNotReadableException(HttpMessageNotReadableException exception) {
        log.error("全局异常捕获 参数格式不正确", exception);
        return ResponseResult.error(HttpCode.BAD_REQUEST, exception.getMessage());
    }

    private ResponseObject<?> getByBindingResult(BindingResult bindingResult) {
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        if (fieldErrors.isEmpty()) {
            log.error("全局异常捕获 捕获到了参数校验错误,{}", bindingResult);
            return ResponseResult.error(HttpCode.BAD_REQUEST, bindingResult.toString());
        } else {
            FieldError fieldError = fieldErrors.get(0);
            return ResponseResult.error(HttpCode.BAD_REQUEST, fieldError.getDefaultMessage());
        }
    }

    @ExceptionHandler({MappingException.class})
    public ResponseObject<?> handleMappingException(Exception exception) {
        log.error("全局异常捕获：对象转化{}", exception.getMessage());
        return ResponseResult.error(HttpCode.INTERNAL_SERVER_ERROR, exception.getMessage());
    }

    @ExceptionHandler({Exception.class})
    public ResponseObject<?> handleException(Exception exception) {
        log.error("全局异常捕获：{}", exception.getMessage());
        return ResponseResult.error(HttpCode.INTERNAL_SERVER_ERROR, exception.getMessage());
    }
}
